const {getDmg,reduceResistanceK,lvSuppressK,objValueAdd } = require("../libs/apis.js")

const WEAPONS = require("./weapons.js");

const CLIPDATA_TYPE = {
    max:{
        fixedhp: 298.75,
        fixedAtt: 19.45,
        fixdefence: 23.15,
        reaction : 23.31,
        attRate: 5.83, 
        hpRate: 5.83, 
        criticalRate: 3.89,
        criticalStrike: 7.77,
        defRate: 7.29,
        charging: 6.48
    },
    mid:{
        fixedhp: 253.94,   // 209.13  239   268.88   298.75
        fixdefence: 19.675, // 16.2   18.52  20.83  23.15
        fixedAtt: 16.535,   //  13.62   15.56   17.51  19.45
        reaction : 19.815,  // 16.32   18.65  20.98  23.31
        attRate: 4.955,  // 4.08  4.66  5.25  5.83
        hpRate: 4.955,   // 4.08  4.66  5.25  5.83
        criticalRate: 3.305,   //  2.72  3.11   3.5   3.89
        criticalStrike: 6.605,  //  5.44  6.22  6.99  7.77
        defRate: 6.195,   //  5.1  5.83  6.56   7.29
        charging: 5.505  //  4.53   5.18   5.83   6.48
    }
}

const CLIPDATA = CLIPDATA_TYPE.mid

const CONFIG = {
    chance: 4,
    your_lv: 90,
    enemy_lv: 90,
    clips_main: {
        fixedHp: 4780,
        fixedAtt:311,
        reaction: 187,
        dmgRate: 46.6,
        criticalRate: 31.1,
    },
    clips_initial: [
        ["reaction", "attRate", "criticalRate", "criticalStrike"],
        ["reaction", "attRate", "criticalRate", "criticalStrike"],
        ["charging", "attRate", "criticalRate", "criticalStrike"],
        ["reaction", "attRate", "criticalRate", "criticalStrike"],
        ["charging", "attRate", "reaction", "criticalStrike"]
    ],
    reactionK : 2,
    reactionDmgAdd: 0,
    buffs: [  
        { reaction: 80 + 50*3},  // 饰金
        // { dmgRate: 15, jk: 30},  // 草套
    ]
}

let charaters = {
    units : {
        name: "纳西妲", 
        dmgZhi: 0,
        charging: 100,
        reaction: 115.2,
        dmgRate: 0,
        defRate: 0,
        defence: 630.21, // 653
        weapontype: "magic",
        attRate: 0,
        hp:10360,
        base: 298.97,     // 299.97
        criticalRate: 5,    
        criticalStrike: 50,
        skills: {
            a: [
                function(data){},
            ]
        }
    },
}

let tmp = {}
CONFIG.clips_initial.forEach(item => {
    item.forEach(item2 => {
        if(tmp[item2]) {
            tmp[item2] += 1
        } else {
            tmp[item2] = 1
        }
    })
});
/*

 a 普攻重击倍率 0.7255 0.6655 0.8257  1.0513      重击 2.376 
 e 所闻遍计 短按 对身边的造成伤害 附加印记 长按 对大范围最多8名敌人附加印记造成伤害
    有印记的人在一定距离内相互连接 对其进行元素反应以及触发绽放时
    草神对该连接内敌人释放 灭净三业 初始每1.9s释放一次 v4改动-> 改为2.5s释放一次
    lv10 短按 1.771 长按 2.347 灭净三业: 1.8576 + 3.7152精通
    lv13 短按 2.091 长按 2.771 灭净三业: 2.193 + 4.386精通

 q 心景幻成 展开领域 根据元素类型角色提升 持续15s cd13.5s 能量50
  10级q
  火 增伤(1名 20 2名 30.1)
  雷 降低间隔(1名 0.3 2名 0.45)
  水 延长时间(1名 4 2名 6.01)
  13级q
  火 增伤(1名 23.63 2名 35.53)
  雷 降低间隔(1名 0.35 2名 0.53)
  水 延长时间(1名 4.73 2名 7.09)

  v4加强后
  10级q
  火 增伤(1名 26.78 2名 40.18)
  雷 降低间隔(1名 0.45 2名 0.67)
  水 延长时间(1名 6.02 2名 9.03)
  13级q
  火 增伤(1名 31.62 2名 47.43)
  雷 降低间隔(1名 0.53 2名 0.79)
  水 延长时间(1名 7.11 2名 10.66)

 天赋
 q后根据队伍里元素精通最高的角色的20% 提高q站场范围内角色精通 最高提高200精通 => v4改动为 25% 250
 根据草神精通超过200的部分提升e灭净三业增伤爆击  每点精通提升(0.1/0.03) 最高提升80/24

 1 q后 额外计入火雷水角色1名
 2 处于印记下的敌人 燃烧绽放反应触发暴击 固定双爆20/100 相当于1.2期望 触发激化时 8s降低防御30(17.6%收益)
 3 e+3
 4 附近有印记敌人越多时 草神获得精通越多 100/120/140/160
 5 q+3
 6 q后草神普攻重击对印记连接的敌人触发 灭净三业·业障除(200%攻击 400%精通) 0.2s触发一次 最多释放6次

 伤害计算 打激化 ~草神放后台 不吃天赋的提高精通
 词条为各部位初始4 强化4次 词条数值为平均值 程序算法分析最优分配 

    0命饰金 精草爆
            专武(1) 攻击1361.568 双爆69.15/175.495 精通876.46 伤害:灭净三业1.7678w 灭净三业激化3.4869w   p:234128
    1命饰金 精草爆
            专武(1) 攻击1361.568 双爆69.15/175.495 精通876.46 伤害:灭净三业1.8354w 灭净三业激化3.6202w   p:243159
    2命饰金 精草爆
            专武(1) 攻击1361.568 双爆69.15/175.495 精通876.46 伤害:灭净三业2.1593w 灭净三业激化4.2591w   p:328660
    3命饰金 精草爆
            专武(1) 攻击1361.568 双爆69.15/175.495 精通876.46 伤害:灭净三业2.5491w 灭净三业激化4.64897w   p:369046
    4命饰金 精草爆 +160精通
            专武(1) 攻击1361.568 双爆65.845/182.1 精通1036.46 伤害:灭净三业3.0135w 灭净三业激化5.4142w   p:430468
    6命饰金 精草爆
            专武(1) 攻击1361.568 双爆65.845/182.1 精通1036.46 伤害:灭净三业3.0706 灭净三业激化5.5167w 满名业障除28004/52465  p:704556
    6命饰金 精草爆
            专武(5) 攻击1361.568 双爆65.845/182.1 精通1036.46 伤害:灭净三业3.5751w 灭净三业激化6.4232w 满名业障除32605/61085  p:820899


    


    1命草神 白字298.97 精通115.2 双爆5/50
    月卡法器 白字510  暴击27.6     特效:普攻和e增伤40

    圣遗物套装效果 饰金套 精通230

    主词条 固定攻击311 精通187 草伤46.6 暴击31.1

    副词条用个人规定的标准毕业规则 初始4词条 每个部位强化4次 数值取平均值 词条分配由程序算法最优分配
    精通19.815  攻击4.955  暴击3.305x2  爆伤6.605x4
    精通19.815x4  攻击4.955  暴击3.305  爆伤6.605x2
    充能  攻击4.955  暴击3.305  爆伤6.605x5
    精通19.815  攻击4.955  暴击3.305  爆伤6.605x5
    精通19.815  攻击4.955  充能  爆伤6.605x5
    副词条合计 精通138.705 攻击24.775 暴击16.525 爆伤138.705

    合计面板 白字809 固定攻击311 攻击24.775 精通671 双爆80.225/188.705

    天赋 q范围内的站场角色+精通 最高+250   加值是最高精通角色的精通25%   
    吃了天赋后精通变为 838. 精通

    天赋 精通超过200的部分 3%转化为e暴击 最高 24%  10%转化为e增伤 最高80%
    这里是  19.159暴击和63.86增伤

    e的期望伤害计算
    10级e倍率 185.76%攻击 + 371.52%精通
    e吃的效果 天赋的19.159暴击和63.86增伤 月卡武器的e增伤40 q的增伤26.78
    蔓激化附加伤害值为  1447 * 1.25 * (1 + (5*精通)/(精通+1200)) = 5529

    伤害值为 (白字x攻击+固定攻击)x倍率 + 精通x倍率 + 蔓激化伤害值 = 2452.83 + 3115.678 + 5529 = 11097.5
    吃了天赋后暴击期望系数为 2.875
    增伤为 46.6+40+26.78+63.86 = 177.24 = 系数2.7724
    抗性和防御乘取通用 0.45系数 10抗性和同等级敌人
    e激化的平均期望伤害 = 11097.5 x 2.875 x 2.7724 x 0.45 = 39804

    以下进行模拟一套站场连段的总输出 就不再像上面一样写详细过程了 只列结果
    站场草神 饰金套 打激化 不吃其他拐
    0命月卡法器 383511   千夜浮梦(1/5) 393785/469941
    1命月卡法器 397450   千夜浮梦(1/5) 408360/484515
    2命月卡法器 516702   千夜浮梦(1/5) 533089/631202
    3命月卡法器 554387   千夜浮梦(1/5) 574002/678820
    4命月卡法器 661545   千夜浮梦(1/5) 618255/730725   4命加精通 弥补了月卡武器没精通的不足
    5命月卡法器 674448   千夜浮梦(1/5) 630802/743273
    6命月卡法器 966805   千夜浮梦(1/5) 913504/1070607   满命有待验证 满命6发不知道激化率如何 目前是按照3发激化3发不激化算的

    当然还有很多人只打算后台草神的 那就不适合用月卡法器了 月卡法器得普攻来获得e增伤
    只打后台的可以流浪打打爆发 或者通用的专武 或者万国/魔导 神子专武叠满伤害跟专武差不多
    万国和魔导伤害差距不大(略次于专武10%~13%) 看特效触发适不适合你的队伍
*/

let cons = 6 // 命座
let chooseIndex = 5; // 查看结果索引
let cid = "units"
let count_kit = 0;
let combination = getCombination(Array(5*CONFIG.chance + 1).fill().map((_,i)=>i), CONFIG.chance, Object.entries(tmp))
let clips_initial_data = calc_clips_initial()
let fs = require("fs")
calc(combination);
function calc(clipSecondData) {
    let charactersDmg = [];
    clipSecondData = clipSecondData.map(clipSecondDataItem => {
        let clipSecond = {}
        clipSecond.des = clipSecondDataItem;
        clipSecond.data = {} 
        for (let secondKey in clipSecond.des) {
            let count =  clipSecond.des[secondKey]
            clipSecond.data[secondKey] = count * CLIPDATA[secondKey]
        }
        return clipSecond
    })
    
    Object.values(WEAPONS).forEach(weapon => {
        if(charaters[cid].weapontype && weapon.weapontype != charaters[cid].weapontype && weapon.weapontype!="all") {return}
        charactersDmg.push(getDMG([charaters[cid],weapon,clips_initial_data,{...CONFIG.clips_main}], clipSecondData, (data,second) => {
            count_kit++;
            data = objValueAdd([data, ...CONFIG.buffs]);
            data.hp = data.hp*(1 + (data.hpRate||0)/100) + data.fixedHp;
            
            if(weapon.skill) { weapon.skill(data); }
            
            if(cons >= 4) {
                data.reaction += 160
            }

            // 站q内时加精通
            let reaAdd = data.reaction * 0.25
            if(reaAdd > 250) {reaAdd = 250}
            data.reaction += reaAdd 

            let rea = { reaction:data.reaction, reactionQ:CONFIG.reactionK, reactionDmgAdd:data.reactionDmgAdd || 0 }
            
            // 根据草神精通超过200的部分提升e灭净三业双爆  每点精通提升(0.1/0.03) 最高提升80/24
            let eMJCR = (data.reaction>200?data.reaction - 200 : 0) * 0.03
            if(eMJCR > 24) { eMJCR = 24 }
            let eMJDmg = (data.reaction>200?data.reaction - 200 : 0) * 0.1
            if(eMJDmg > 80) { eMJDmg = 80 }
           
            data.eDmgRate = data.eDmgRate||0;
            // q加成
            if(cons >= 5) {
                data.eDmgRate += 47.43
            } else if(cons >= 1) {
                data.eDmgRate += 40.18
            } else {
                data.eDmgRate += 26.78
            }

            let jf = 0
            if(cons >= 2) {
                jf = 30
            }

            // lv10 短按 1.771 长按 2.347 灭净三业: 1.8576 + 3.7152精通
            // lv13 短按 2.091 长按 2.771 灭净三业: 2.193 + 4.386精通
            let eRateList = [2.347, 1.8576, 3.7152]
            if(cons >= 3) {
                eRateList = [2.771, 2.193, 4.386]
            }
            let jhDmgZhi = 1447 * 1.25 * (1 + (5*data.reaction)/(data.reaction+1200))
            // 普攻重击倍率 0.7255 0.6655 0.8257  1.0513      重击 2.376 
            let a1Dmgage = getDmg({
                data: {
                    ...data,
                    dmgRate: data.dmgRate + (data.a1dmg||0),
                },
                rate: 0.7255
            }).qw * reduceResistanceK(10 - (data.jk||0)) * lvSuppressK(CONFIG.your_lv, CONFIG.enemy_lv, jf);
            let a1DmgageJH = getDmg({
                data: {
                    ...data,
                    dmgRate: data.dmgRate + (data.a1dmg||0),
                    dmgZhi: jhDmgZhi
                },
                rate: 0.7255
            }).qw * reduceResistanceK(10 - (data.jk||0)) * lvSuppressK(CONFIG.your_lv, CONFIG.enemy_lv, jf);
            let a2Dmgage = getDmg({
                data: {
                    ...data,
                    dmgRate: data.dmgRate + (data.a1dmg||0),
                },
                rate: 0.6655
            }).qw * reduceResistanceK(10 - (data.jk||0)) * lvSuppressK(CONFIG.your_lv, CONFIG.enemy_lv, jf);
            let a2DmgageJH = getDmg({
                data: {
                    ...data,
                    dmgRate: data.dmgRate + (data.a1dmg||0),
                    dmgZhi: jhDmgZhi
                },
                rate: 0.6655
            }).qw * reduceResistanceK(10 - (data.jk||0)) * lvSuppressK(CONFIG.your_lv, CONFIG.enemy_lv, jf);
            let a3Dmgage = getDmg({
                data: {
                    ...data,
                    dmgRate: data.dmgRate + (data.a1dmg||0),
                },
                rate: 0.8257
            }).qw * reduceResistanceK(10 - (data.jk||0)) * lvSuppressK(CONFIG.your_lv, CONFIG.enemy_lv, jf);
            let a3DmgageJH = getDmg({
                data: {
                    ...data,
                    dmgRate: data.dmgRate + (data.a1dmg||0),
                    dmgZhi: jhDmgZhi
                },
                rate: 0.8257
            }).qw * reduceResistanceK(10 - (data.jk||0)) * lvSuppressK(CONFIG.your_lv, CONFIG.enemy_lv, jf);
            let a4Dmgage = getDmg({
                data: {
                    ...data,
                    dmgRate: data.dmgRate + (data.a1dmg||0),
                },
                rate: 1.0513
            }).qw * reduceResistanceK(10 - (data.jk||0)) * lvSuppressK(CONFIG.your_lv, CONFIG.enemy_lv, jf);
            let a4DmgageJH = getDmg({
                data: {
                    ...data,
                    dmgRate: data.dmgRate + (data.a1dmg||0),
                    dmgZhi: jhDmgZhi
                },
                rate: 1.0513
            }).qw * reduceResistanceK(10 - (data.jk||0)) * lvSuppressK(CONFIG.your_lv, CONFIG.enemy_lv, jf);

            let eShiFang = getDmg({
                data: {
                    ...data,
                    dmgRate: data.dmgRate + (data.eDmgRate||0) + (data.eDmgAdd||0),
                },
                rate: eRateList[0]
            }).qw * reduceResistanceK(10 - (data.jk||0)) * lvSuppressK(CONFIG.your_lv, CONFIG.enemy_lv, jf);
            let eShiFangJH = getDmg({
                data: {
                    ...data,
                    dmgRate: data.dmgRate + (data.eDmgRate||0) + (data.eDmgAdd||0),
                    dmgZhi: jhDmgZhi
                },
                rate: eRateList[0]
            }).qw * reduceResistanceK(10 - (data.jk||0)) * lvSuppressK(CONFIG.your_lv, CONFIG.enemy_lv, jf);
            let eMJ = getDmg({
                data: {
                    ...data,
                    criticalRate: data.criticalRate + eMJCR,
                    dmgRate: data.dmgRate + (data.eDmgRate||0) + eMJDmg  + (data.eDmgAdd||0),
                    dmgZhi: data.reaction * eRateList[2]
                },
                rate: eRateList[1]
            }).qw * reduceResistanceK(10 - (data.jk||0)) * lvSuppressK(CONFIG.your_lv, CONFIG.enemy_lv, jf);
            let eMJJH = getDmg({
                data: {
                    ...data,
                    criticalRate: data.criticalRate + eMJCR,
                    dmgRate: data.dmgRate + (data.eDmgRate||0) + eMJDmg  + (data.eDmgAdd||0),
                    dmgZhi: jhDmgZhi + data.reaction * eRateList[2]
                },
                rate: eRateList[1]
            }).qw * reduceResistanceK(10 - (data.jk||0)) * lvSuppressK(CONFIG.your_lv, CONFIG.enemy_lv, jf);
            
            let eMJLiuMin = getDmg({
                data: {
                    ...data,
                    criticalRate: data.criticalRate + eMJCR,
                    dmgRate: data.dmgRate + (data.eDmgRate||0) + eMJDmg  + (data.eDmgAdd||0),
                    dmgZhi: data.reaction * 4
                },
                rate: 2
            }).qw * reduceResistanceK(10 - (data.jk||0)) * lvSuppressK(CONFIG.your_lv, CONFIG.enemy_lv, jf);
            let eMJLiuMinJH = getDmg({
                data: {
                    ...data,
                    criticalRate: data.criticalRate + eMJCR,
                    dmgRate: data.dmgRate + (data.eDmgRate||0) + eMJDmg  + (data.eDmgAdd||0),
                    dmgZhi: jhDmgZhi + data.reaction * 4
                },
                rate: 2
            }).qw * reduceResistanceK(10 - (data.jk||0)) * lvSuppressK(CONFIG.your_lv, CONFIG.enemy_lv, jf);
            
            

            if(data.phyRate) { // 物理特效伤害
                data.phyDmg = getDmg({data:{...data, dmgRate:0}, rate:data.phyRate}).qw * reduceResistanceK(10) * lvSuppressK(CONFIG.your_lv, CONFIG.enemy_lv);  // 
            }

            // 0命9hit 1命10hit 5命10hit      0.45 0.67 0.79 2.05/1.83/1.71
            let point = eShiFang * 1 + eMJ * 0 + eMJJH*(cons>1? 8 : 7) + (data.phyDmg||0) + (a1DmgageJH + a2Dmgage + a3Dmgage + a4DmgageJH) * 3;
            if(cons >= 6) {
                point += (eMJLiuMin * 3 + eMJLiuMinJH*3)
            }
            let attack = data.base *(1 + data.attRate/100) + data.fixedAtt;
            return {point, data, second, attack, dmg:{eShiFang,eShiFangJH,eMJ,eMJJH,eMJLiuMin,eMJLiuMinJH,reaAdd,jhDmgZhi, aDmg: {
                a1Dmgage,a1DmgageJH,a2Dmgage,a2DmgageJH,a3Dmgage,a3DmgageJH,a4Dmgage,a4DmgageJH
            }}}
        }))
    })
    
    charactersDmg.sort((a,b)=>{
        return (b.point)-(a.point);
    });
    let sortf = JSON.parse(fs.readFileSync("./sort.js").toString()) 
    let choose = charactersDmg[chooseIndex];
    console.log(choose);
    fs.writeFileSync("./ret.js", JSON.stringify(choose))

    let name = choose.data.name
    let keys = "_"+choose.data.weaponname+"_6命无拐2+2毕业"
    let sortfData = {key: name+keys, point:choose.point, dmg:JSON.parse(JSON.stringify(choose.dmg))}
    if(sortfData.point && sortfData.point > 0) {
        let org = sortf.findIndex(item3 => item3.key == sortfData.key)
        if(org >= 0){
            sortf[org] = sortfData
        } else {
            sortf.push(sortfData)
        }
        sortf.sort((b,a) => a.point-b.point)
        // fs.writeFileSync("./sort.js", JSON.stringify(sortf))
    }
    console.log(charactersDmg.map((v, n)=>{
        return  `(${n})得分: ${v.data.weaponname} : ${v.point.toFixed(0)}`
    }));
    console.log(count_kit);
}

function getDMG(dataarr, clipSecond, getRet){
    clipSecond = clipSecond.map(second => {
        let panel = objValueAdd([...dataarr, second.data]);
        return  getRet(panel, second)
    })
    clipSecond.sort((b,a)=> a.point-b.point)
    return clipSecond[0]
}

function calc_clips_initial () {
    let clips = CONFIG.clips_initial.map(v => {
        let tmp = {};
        v.forEach(v2 => {
            tmp[v2] = CLIPDATA[v2]
        })
        return tmp
    })
    let data = {}
    clips.forEach(item => {
        for (const key in item) {
            data[key] = data[key]? (data[key]+item[key]) : item[key]
        }
    })
    return data
}
function getCombination (arr, chance, entrys) {
    let num = 5
    var r = [];
    (function f(t, a, n) {
        if (n === 0) {
            if(t.reduce((a1,b1) => a1+b1) !== chance * 5){return}
            let ret = {}
            for (let i in t) {
                if(t[i] > entrys[i][1]*chance){return}
                ret[entrys[i][0]] = t[i]
            }
            r.push(ret)
            return ;
        }
        for (var i = 0, l = a.length; i < l; i++) {
            f(t.concat(a[i]), a, n - 1);
        }
    })([], arr, num);
    return r;
}